#pragma once
/* 
* COPYRIGHT 2012 Mafahir Fairoze
* 
* This file is part of Vector Template Library (Vtl) v1.0.
* (Project Website : http://mafahir.wordpress.com/projects/neuralplusplus)
* 
* Vector Template Library (Vtl) v1.0 is a free software. You can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
* 
* Vector Template Library (Vtl) v1.0 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License <http://www.gnu.org/licenses/> for more details.
*/

#include "Vtl/eigen.h"
#include "Vtl/AABBox.h"
#include <Eigen/StdVector>

namespace Vtl
{
	template <typename Scalar, int Dimension>
	class Polygon
	{
	public:
		typedef Eigen::Matrix<Scalar, Dimension, 1> VectorType;
		typedef std::vector<VectorType, Eigen::aligned_allocator<VectorType>> Container;
		typedef typename Container::size_type size_type;
		typedef Eigen::ParametrizedLine<Scalar,Dimension> ParametrizedLine;
		typedef AABBox<double, Dimension> BoundingBox;

		/*!
		*  \brief Default constructor.
		*/
		Polygon(void)
		{
		}

		/*!
		*  \brief Returns the vertex at index.
		*  \param[in] _Index 
		*  \return VectorType & 
		*/
		VectorType & operator[](const size_type &_Index)
		{
			return vertices[_Index];
		}

		/*!
		*  \brief Returns the vertex at index.
		*  \param[in] _Index 
		*  \return const VectorType & 
		*/
		const VectorType & operator[](const size_type &_Index) const
		{
			return vertices[_Index];
		}

		/*!
		*  \brief Appends another vertex into the polygon.
		*  \param[in] _Vertice 
		*/
		void Append(const VectorType &_Vertice)
		{
			vertices.push_back(_Vertice);
			bounding_box.AddInPoint(_Vertice);
		}

		/*!
		*  \brief Returns the vertex count in the array.
		*  \return size_type 
		*/
		size_type getVertexCount() const
		{
			return vertices.size();
		}

		/*!
		*  \brief Recalculates the bounding box for the existing set of vertices.
		*/
		void RecalculateBoundingBox()
		{
			bounding_box.Reset();
			for(int i=0;i<vertices.size();i++)
				bounding_box.AddInPoint(vertices[i]);

		}

		/*!
		*  \brief Returns the bounding box.
		*  \note If the vertices changes, bounding box needs to be recalculated.
		*  \return const BoundingBox & 
		*/
		const BoundingBox & getBoundingBox()
		{
			return bounding_box;
		}

	protected:
		Container vertices;
		BoundingBox bounding_box;
	};

	typedef Polygon<double, 3> Polygon3d;
	typedef Polygon<double, 2> Polygon2d;
	typedef Polygon<float, 3> Polygon3f;
	typedef Polygon<float, 2> Polygon2f;
	typedef Polygon<int, 3> Polygon3i;
	typedef Polygon<int, 2> Polygon2i;
};
